#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "tokens.h"
#include "lexer.h"

FILE *tape;
char lexeme[256];
int lookahead;


void assign(void){ 
}

int isOPLUS(FILE * tape)
{
    int             head = getc(tape);
    switch (head) {
    case '+':
    case '-':
        return OPLUS;
    }
    ungetc(head,tape);
    return 0;
}

int isOTIMES(FILE * tape)
{
    int             head = getc(tape);
    switch (head) {
    case '*':
    case '/':
         return OTIMES;
    }
    ungetc(head,tape);
    return 0;
}

int isHEXA(FILE * tape)
{
   int head;
   if(isdigit(head  = getc(tape)) || ('a' <= tolower(head) && tolower(head) <= 'f')){
      while(isdigit(head  = getc(tape)) || ('a' <= tolower(head) && tolower(head) <= 'f'));
      ungetc(head,tape);
      return 1;  
   }
   else{
     ungetc(head,tape);
     return 0;
	}    
}
int isOCTA(FILE * tape)
{
   int head;
   if((head  = getc(tape)) >= '0'  && head  <= '7' ){
      while((head  = getc(tape)) >= '0'  && head  <= '7' );
      ungetc(head,tape);
      return 1;
   }
   else{
     ungetc(head,tape); 	
     return 0;
	}
}

int isID(FILE * tape){
    int             head = getc(tape);
    if (isalpha(head)) {
        while (isalnum(head = getc(tape)));
        ungetc(head, tape);
        return ID;
    }
    ungetc(head, tape);
    return 0;
}

int isUINT(void){
    int i = 0;
    lexeme[i] = getc(tape);
    if (isdigit(lexeme[i])) {
        if (lexeme[i] == '0') {
            lexeme[1] = 0;
            return UINT;
        }
        while (isdigit(lexeme[++i] = getc(tape)));
        ungetc(lexeme[i], tape);
        lexeme[i] = 0;
        return UINT;
    }
    ungetc(lexeme[i], tape);
    return 0;
}

/*
 * floating = UINT ('.' digit* EXPNotation? | EXPNotation) | '.' digit+ EXPNotation?
 *
 * EXPNotation = 'E' ('+'|'-')? digit+
 */

int isFLOAT()
{
	int i = 0;
	lexeme[i] = getc(tape);
    if (lexeme[i] == 'E' || lexeme[i] == 'e') {
        lexeme[++i] = getc(tape);
        if (lexeme[i] == '+' || lexeme[i] == '-')
            lexeme[++i] = getc(tape);
        if (isdigit(lexeme[i])) {
            while (isdigit(lexeme[++i] = getc(tape)));
            ungetc(lexeme[i], tape);
            lexeme[i] = 0;
            return 1;
        }
        fprintf(stderr, "ilegal exponential notation\n");
        exit(-2);
    }
    ungetc(lexeme[i], tape);
    lexeme[i] = 0;
    return 0;
}
int isEXPNotation(){
  
  
}
int isNUM(void)
{
    printf("ALOW");
	int i = 0;
    if (isUINT()) {
        if ((lexeme[i] = getc(tape)) == '.') {
            while (isdigit(lexeme[++i] = getc(tape)));
            ungetc(lexeme[i], tape);
            lexeme[i] = 0;
            isEXPNotation();
            return FLOAT;
        }
        ungetc(lexeme[i], tape);
        lexeme[i] = 0;
        if (isEXPNotation())
            return FLOAT;
        return UINT;
    }
    if ((lexeme[i] = getc(tape)) == '.') {
        if (isdigit(lexeme[++i] = getc(tape))) {
            while (isdigit(lexeme[++i] = getc(tape)));
            ungetc(lexeme[i], tape);
            lexeme[i] = 0;
            isEXPNotation();
            return FLOAT;
        }
        ungetc(lexeme[i--], tape);
        ungetc('.', tape);
        return 0;
    }
    ungetc(lexeme[i], tape);
    return 0;
}

int isRELOP(void)
{
    int i = 0;
    switch (lexeme[i] = getc(tape)){
       case '<':
		if ((lexeme[++i] = getc(tape)) == '>')
		{
			strcpy(lexeme, "<>");
			return RELOP;
		}
		else if (lexeme[i] == '='){
			strcpy(lexeme, "<=");
			return RELOP;
		}
		ungetc(lexeme[i], tape);
		strcpy(lexeme, "<");
		return RELOP; 
       case '>':
        if ((lexeme[++i] = getc(tape)) == '=')
		{
			strcpy(lexeme, ">=");
			return RELOP;
		}
        ungetc(lexeme[i], tape);
		strcpy(lexeme, ">");
		return RELOP;
       case '=':
		lexeme[i+1]=0;
		return RELOP;
	   default:
		ungetc(lexeme[i], tape);
	   return 0;
    }
}

int isASSGNMT(void)
{
	int i = 0;
    if((lexeme[i++]=getc(tape))==':')
	{
      if((lexeme[i++]=getc(tape))=='=')
	  {
        lexeme[i] = 0;
		return ASSGNMT;
      }
      ungetc(lexeme[--i],tape);
      lexeme[i]=0;
      return lexeme[0];
    }
	ungetc(lexeme[--i],tape);
	return 0;
}

int isLEQ(void)
{
	int i = 0;
    if((lexeme[i++]=getc(tape))=='<')
	{
      if((lexeme[i++]=getc(tape))=='=')
	  {
		lexeme[i] = 0;
		return LEQ;
      }
      ungetc(lexeme[--i],tape);
      lexeme[i]=0;
      return lexeme[0];
    }
	ungetc(lexeme[--i],tape);
	return 0;
}

int isNEQ(void)
{
	int i = 0;
    if((lexeme[i++]=getc(tape))=='<')
	{
      if((lexeme[i++]=getc(tape))=='>')
	  {
        lexeme[i] = 0;
        return NEQ;
      }
      ungetc(lexeme[--i],tape);
      lexeme[i]=0;
      return lexeme[0];
    }
	ungetc(lexeme[--i],tape);
	return 0;
}

int isGEQ(void)
{
	int i = 0;
    if((lexeme[i++]=getc(tape))=='>')
	{
      if((lexeme[i++]=getc(tape))=='=')
	  {
        lexeme[i] = 0;
        return GEQ;
      }
      ungetc(lexeme[--i],tape);
      lexeme[i]=0;
      return lexeme[0];
    }
	ungetc(lexeme[--i],tape);
	return 0;
}





/* PARSER INTERFACE */

gettoken(FILE * tape)
{
  /* tape head */
    int             head;
  /* temporary token */
    int             token;
  /* isspaces */
   
    while (isspace(head = getc(tape))){
    ungetc(head, tape);
  /* test which automaton can acept */
    if (token = isID(tape)){
	printf("ID\n");
        return token;}
    if (token = isNUM()){ 
      printf("NUM\n");
        return token;}
    if (token = isFLOAT(tape)){
      printf("FLOAT\n");
        return token;}
    if (token = isOPLUS(tape)){
	printf("OPLUS\n");
        return token;}
     
    if (token = isOTIMES(tape)){
	printf("OTIMES\n");
        return token;}

    if (token = isLEQ()){
	printf("LEQ\n");
        return token;}
  
    if (token = isGEQ()){
	printf("GEQ\n");
        return token;}

    if (token = isNEQ()){
	printf("NEQ\n");
        return token;}

    if (token = isASSGNMT()){
	printf("ASSGNMT\n");
        return token;}
  
       
    lexeme[1] = 0;
    return lexeme[0] = getc(tape);
    }    
}


void 
match(int expected)
{
    if (expected == lookahead) 
	{
        lookahead = gettoken(tape);
    } 
    else 
	{
        fprintf(stderr, "token mismatch\naborting...\n");
        exit(-1);
    }
}